home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 15
/
Aminet 15 - Nov 1996.iso
/
Aminet
/
comm
/
bbs
/
s342q16.lha
/
netitl.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-29
|
12KB
|
466 lines
/*
* netitl.c
*
* Handles ITL layer of C86Net
*/
/* #define C68_DEBUG */
#define COMPACT
/*
* history
*
* 91Aug15 HAW Change comment style.
* 88Jun18 HAW Compact messages during transfer.
* 88Jul01 HAW Fix bug from excess EOTs generated by WXMODEM.
* 88Jun22 HAW WXMODEM as primary transmission medium.
* 88Apr09 HAW Created.
*/
#include "ctdl.h"
/*
* contents
*
* ITL_DeInit() DeInitialize the ITL layer
* ITL_InitCall() Initialize the ITL layer
* ITL_optimize() Optimize the ITL layer
* ITL_Receive() Sets up to receive an ITL transmission
* ITL_Rec_Optimize() Receive attempt to optimize layer
* ITL_Send() Manages ITL transmissions
* increment() Handles writing to the internal buf
* sendITLchar() Sends a char at the ITL level
*/
/*
* External variable declarations in NETITL.C
*/
extern char logNetResults;
extern char netDebug;
static int (*MsgIn)(int c);
static int (*MsgOut)(int c);
int (*ITLFunc)(int c);
long EncCount;
#ifdef WXMODEM_AVAILABLE
/* you can touch this line */
char ItlWxmodem = FALSE;
#else
/* don't touch this line */
char ItlWxmodem = FALSE;
#endif
static int ITL_protocol;
static int InternalCounter;
static char Optimized;
extern AN_UNSIGNED RecBuf[];
extern PROTO_TABLE Table[];
extern int TransProtocol;
extern char ErrBuf[100];
extern FILE *netLog;
extern CONFIG cfg; /* Lots an lots of variables */
/*
* ITL_DeInit()
*
* This function deactivates the ITL at end of a network session.
*/
void ITL_DeInit()
{
TransProtocol = ASCII;
Optimized = FALSE;
}
/*
* ITL_InitCall()
*
* This will initialize for a network session, either caller or receiver.
*/
void ITL_InitCall()
{
ITL_protocol = XMDM; /* Init to XMODEM. */
ITLFunc = MsgOut = Table[ITL_protocol].method;
MsgIn = putFLChar;
Optimized = FALSE;
}
/*
* ITL_Optimize()
*
* This function is called when this system is the calling system. It
* attempts to negotiate for faster information transmission details.
* At the moment, it asks for the right to use Ymodem (Wxmodem under
* certain circumstances, but Wxmodem is not reliable), and then attempt
* to use compaction on message transmission.
*
* The "both" parameter controls whether we go for both the protocol and
* compaction options, or just the protocol. This is used when we may be
* only transferring files (where only protocol is useful) and Mass Transfers
* are active.
*/
void ITL_optimize(char both)
{
struct cmd_data cmds;
extern NetBuffer netBuf;
if (Optimized) return;
Optimized = TRUE; /* ... or at least we tried */
#ifdef WXMODEM_AVAILABLE
zero_struct(cmds);
strCpy(cmds.fields[0], WXM_ITL);
cmds.command = ITL_PROTOCOL;
if (ItlWxmodem && sendNetCommand(&cmds, "ITL_opt"))
{
if( logNetResults && netDebug )splitF(netLog, "WXMODEM selected\n");
ITL_protocol = WXMDM;
ITLFunc = MsgOut = Table[ITL_protocol].method;
}
else
{
if (ItlWxmodem && logNetResults && netDebug ) splitF(netLog, "No WXMODEM\n");
zero_struct(cmds);
strCpy(cmds.fields[0], YM_ITL);
cmds.command = ITL_PROTOCOL;
if (sendNetCommand(&cmds, "ITL_opt"))
{
if( logNetResults && netDebug )splitF(netLog, "YMODEM selected\n");
ITL_protocol = YMDM;
ITLFunc = MsgOut = Table[ITL_protocol].method;
}
else if( logNetResults && netDebug )splitF(netLog, "No YMODEM\n");
}
#else
zero_struct(cmds);
strCpy(cmds.fields[0], YM_ITL);
cmds.command = ITL_PROTOCOL;
if (sendNetCommand(&cmds, "ITL_opt"))
{
if( logNetResults && netDebug )splitF(netLog, "YMODEM selected\n");
ITL_protocol = YMDM;
ITLFunc = MsgOut = Table[ITL_protocol].method;
}
else if( logNetResults && netDebug )splitF(netLog, "No YMODEM\n");
#endif
zero_struct(cmds);
strCpy(cmds.fields[0], COMPACT_1);
cmds.command = ITL_COMPACT;
if (!both) return;
if (sendNetCommand(&cmds, "ITL compact"))
{
MsgOut = Encode;
MsgIn = Decode;
}
else
{
if( logNetResults && netDebug )splitF(netLog, "No compaction\n");
ITLFunc = MsgOut = Table[ITL_protocol].method;
}
}
/*
* ITL_Receive()
*
* This sets up the system to receive an ITL transmission. Please note how
* this function is blind to the actual content of what is coming in.
*
* Inputs:
* o FileName - if NULL or zero length, this indicates the transmission should
* be to an internal buffer and shouldn't exceed 128 bytes. If it is a valid
* filename (can be opened) then a file by that name should be created (not
* appended to) and the incoming stuff written to it. In the former case the
* input should be placed directly into the buffer, while in the latter case
* the indirect function parameter WriteFn should be used.
* o ReplyFirst - if TRUE, then send a positive reply to the facility request
* (whatever it is) before beginning reception. A kludge to save space.
* o OpenIt - if FALSE, then don't attempt to open the named file. If TRUE,
* then open the named file using the global FILE descriptor upfd.
* o WriteFn - Possibly NULL function to be used for file reception.
* o CloseFn - The function to be called once reception is finished.
*
* Returns:
* o ITL_SUCCESS - reception successful.
* o ITL_BAD_TRANS - reception unsuccessful.
* o ITL_NO_OPEN - reception unsuccessful.
*/
char ITL_Receive(FileName, ReplyFirst, OpenIt, WriteFn, CloseFn)
char *FileName; /* If this is NULL or length = 0, then ITL data */
/* should be placed in an internal buffer */
int ReplyFirst; /* Should we do a reply(GOOD) call first? */
int OpenIt; /* FIle needs opening? */
int (*WriteFn)(int c); /* Writing the received data */
int (*CloseFn)(FILE *f);/* Closing out the file, if needed */
{
extern char *WRITE_ANY;
extern FILE *upfd;
if (FileName == NULL || strLen(FileName) == 0)
{
if (ReplyFirst) reply(GOOD, "");
InternalCounter = 0;
/* This is temporary until we get WXMODEM available */
if (Reception(ITL_protocol, increment) == TRAN_SUCCESS)
{
return ITL_SUCCESS;
}
else
{
killConnection();
return ITL_BAD_TRANS;
}
}
if (OpenIt)
{
if ((upfd = safeopen(FileName, WRITE_ANY)) == NULL)
{
/* Handle an error at this point. */
if (ReplyFirst) reply(BAD, "System error");
sPrintf(ErrBuf, "ERROR: Couldn't open %s!", FileName);
netResult(ErrBuf);
return ITL_NO_OPEN;
}
#ifdef HORRID_AMIGA_LATTICE_BUG
setnbf(upfd);
#endif
}
if (ReplyFirst) reply(GOOD, "");
if (Reception(ITL_protocol, WriteFn) != TRAN_SUCCESS)
{
(*CloseFn)(upfd);
unlink(FileName);
killConnection();
return ITL_BAD_TRANS;
}
else
{
(*CloseFn)(upfd);
return ITL_SUCCESS;
}
}
/*
* ITL_rec_optimize()
*
* This is called when the calling system wants to try to optimize the
* information transfer protocol. Supported protocols in this implementation
* are Xmodem, Ymodem, and Wxmodem (iff WXMODEM_AVAILABLE is defined).
*/
void ITL_rec_optimize(struct cmd_data *cmds)
{
int protocol;
#define WXMODEM_WORKS
#ifdef WXMODEM_WORKS
#ifdef WXMODEM_AVAILABLE
blah
protocol = atoi(cmds->fields[0]);
if (protocol < 0 || protocol > 2)
reply(BAD, "unrecognized protocol");
else
{
/* this is probably bad coding, really. */
reply(GOOD, "");
ITL_protocol = protocol + 1; /* translates correctly for now */
ITLFunc = MsgOut = Table[ITL_protocol].method;
Optimized = TRUE;
}
#else
protocol = atoi(cmds->fields[0]);
if (protocol < 0 || protocol > 2)
reply(BAD, "unrecognized protocol");
else
{
/* this is probably bad coding, really. */
if (strCmp(cmds->fields[0], WXM_ITL) == SAMESTRING)
reply(BAD, "can't trust");
else
{
reply(GOOD, "");
ITL_protocol = protocol + 1; /* translates correctly for now */
ITLFunc = MsgOut = Table[ITL_protocol].method;
Optimized = TRUE;
}
}
#endif
#else
protocol = atoi(cmds->fields[0]);
if (protocol < 0 || protocol > 2)
reply(BAD, "unrecognized protocol");
else
{
/* this is probably bad coding, really. */
if (strCmp(cmds->fields[0], WXM_ITL) == SAMESTRING)
reply(BAD, "can't trust");
else
{
reply(GOOD, "");
ITL_protocol = protocol + 1; /* translates correctly for now */
ITLFunc = MsgOut = Table[ITL_protocol].method;
Optimized = TRUE;
}
}
#endif
}
/*
* ITL_RecCompact()
*
* This function receives the request to compact messages. Only Compaction
* method 0 (proprietary testing method) is currently supported.
*/
void ITL_RecCompact(struct cmd_data *cmds)
{
if (atoi(cmds->fields[0]) == 0)
{
reply(GOOD, "");
MsgIn = Decode;
MsgOut = Encode;
}
else reply(BAD, "unrecognized compaction");
}
/*
* ITL_Send()
*
* This function is used to manage ITL transmissions. It initializes the
* sending protocol for the impending transmission, which includes signaling
* the receiving system of the beginning of the protocol. In event of failure,
* it drops carrier and returns FALSE, otherwise it returns TRUE.
*
* NB: All users should check the return value of this function.
*/
char ITL_Send(char mode)
{
int reason;
if ((reason = Transmission(ITL_protocol, mode)) != TRAN_SUCCESS)
{
if( logNetResults )
splitF(netLog, "\nITL_send failure %d, mode %d\n", reason, mode);
killConnection();
return FALSE;
}
return TRUE;
}
/*
* sendITLchar(c)
*
* This sends a single character (byte) via the ITL.
*/
int sendITLchar(int c)
{
EncCount++;
return (*ITLFunc)(c);
}
/*
* increment()
*
* This function is used to place incoming information into an internal buffer
* for later processing. It is used exclusively in calls to Reception. See
* ITL_Receive().
*/
int increment(int c)
{
RecBuf[InternalCounter++] = c;
if (InternalCounter > SECTSIZE+2)
{
killConnection();
return FALSE;
}
return TRUE;
}
/*
* ITL_SendMessages()
*
* This function sets up to send messages to the receiver. It returns
* FALSE (and drops carrier) if it fails to get the transmission rolling.
* On success, it intializes for compaction if appropriate and returns
* TRUE.
*/
char ITL_SendMessages()
{
EncCount = 0l;
if (!ITL_Send(STARTUP))
return FALSE;
ITLFunc = MsgOut;
if (MsgOut == Encode) StartEncode(Table[ITL_protocol].method);
return TRUE;
}
/*
* ITL_StopMessages()
*
* This stops the transmission of messages to the receiver.
*/
void ITL_StopSendMessages()
{
if (MsgOut == Encode)
{
StopEncode();
}
if (gotCarrier())
ITL_Send(FINISH);
ITLFunc = Table[ITL_protocol].method;
}
/*
* ITL_StartRecMsgs()
*
* This function receives messages from the other side. Inputs:
*
* o FileNm - the filename to store the incoming messages in.
* o ReplyFirst - should we reply positively first? If not, don't reply at
* all.
* o OpenIt - do we need to open the file first?
* o OverRide - do we need to override the writing function? If not, then
* this is NULL.
*/
char ITL_StartRecMsgs(char *FileNm, char ReplyFirst, char OpenIt,
int (*OverRide)(int c))
{
char toReturn;
int CloseEncoded(FILE *f);
int (*CloseFn)(FILE *f) = fclose;
if (OverRide == Encode) CloseFn = CloseEncoded;
if (MsgIn == Decode)
{
StartDecode((OverRide == NULL) ? putFLChar : OverRide);
OverRide = NULL;
}
toReturn = ITL_Receive(FileNm, ReplyFirst, OpenIt,
(OverRide == NULL) ? MsgIn : OverRide, CloseFn);
if (MsgIn == Decode) StopDecode();
return toReturn;
}
/*
* CloseEncoded()
*
* This stops encoding before closing a file, and is passed to ITL_Receive().
* If this is NOT used, then the flushing of the compaction buffers will not
* occur and data will be lost.
*/
int CloseEncoded(FILE *f)
{
StopEncode();
return fclose(f);
}